package com.adcc.automation.communication;

import com.adcc.automation.gui.Controller.MainController;
import com.adcc.automation.gui.event.ConnectStatusEvent;
import com.adcc.automation.service.configuration.ConnectionStatus;
import com.adcc.automation.service.configuration.Operation;
import com.adcc.automation.service.transfer.ActiveMqFactory;
import com.adcc.automation.service.transfer.TransferListener;
import com.adcc.automation.service.util.XmlConverter;
import io.datafx.controller.flow.context.ViewFlowContext;
import lombok.Setter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * GUI 和 service 交互类
 */


public class CommunicationHandler implements TransferListener {
    
    private static final Logger logger = LoggerFactory.getLogger(CommunicationHandler.class);
    
    private static final CommunicationHandler instance = new CommunicationHandler();
    @Setter
    private ViewFlowContext context;//上下文
    
    private ActiveMqFactory activeMqFactory1;
    
    private ActiveMqFactory activeMqFactory2;
    
    public static synchronized CommunicationHandler getInstance() {
        return instance;
    }
    
    public CommunicationHandler init(Map<String, Object> map1,Map<String, Object> map2) {
        
        activeMqFactory1 = new ActiveMqFactory();
        activeMqFactory1.setCommunicationHandler(this);
        activeMqFactory1.setListener(this);
        activeMqFactory2 = new ActiveMqFactory();
        activeMqFactory2.setCommunicationHandler(this);
        activeMqFactory2.setListener(this);
        try {
            activeMqFactory1.setConfig(map1).init(1);
            activeMqFactory2.setConfig(map2).init(2);
            return this;
        } catch (Exception e) {
            logger.error("CommunicationHandler init error {}", e.getMessage());
            throw new RuntimeException(e);
        }
    }
    
    /**
     * 启动
     */
    public void connect() throws Exception {
        try {
            if (activeMqFactory1 != null) {
                new Thread(() -> {
                    try {
                        activeMqFactory1.start();
                    } catch (Exception ex) {
                        logger.error("start activeMq1 run error {}", ex.getMessage());
                    }
                }).start();
            }
            if (activeMqFactory2 != null) {
                new Thread(() -> {
                    try {
                        activeMqFactory2.start();
                    } catch (Exception ex) {
                        logger.error("start activeMq2 run error {}", ex.getMessage());
                    }
                }).start();
            }
        } catch (Exception e) {
            logger.error("CommunicationHandler start error {}", e.getMessage());
            throw new RuntimeException(e);
        }
    }
    
    /**
     * 停止
     */
    public void disconnect() throws Exception {
        try {
            activeMqFactory1.stop();
            activeMqFactory2.stop();
        } catch (Exception e) {
            logger.error("CommunicationHandler stop error {}", e.getMessage());
            throw new RuntimeException(e);
        }
    }
    
    @Override
    public void onData(int source,Operation operation ,String data) {
        MainController mainController = (MainController) context.getRegisteredObject("main");
        if(source == 1){
            switch (operation) {
                case TOPIC -> mainController.updateTopic1(data);
                case FPL_QUEUE -> mainController.updateFplQueue1(data);
                case COMMAND_QUEUE -> mainController.updateCommandQueue1(data);
            }
        }else if(source == 2){
            switch (operation) {
                case TOPIC -> mainController.updateTopic2(data);
                case FPL_QUEUE -> mainController.updateFplQueue2(data);
                case COMMAND_QUEUE -> mainController.updateCommandQueue2(data);
            }
        }
    }
    
    @Override
    public void onState(ConnectionStatus status) {
        logger.info("change status data: {}", status);
        ConnectStatusEvent connectStatusEvent = switch (status) {
            case CONNECTED -> new ConnectStatusEvent("connected");
            case DISCONNECTED -> new ConnectStatusEvent("disconnected");
            case CONNECTING -> new ConnectStatusEvent("connecting");
        };
        MainController mainController = (MainController) context.getRegisteredObject("main");
        mainController.connectHandler(connectStatusEvent);
    }
    
    public void sendMsg(int source,String queue, String data) {
        try {
            MainController mainController = (MainController) context.getRegisteredObject("main");
            if(source == 1) {
                activeMqFactory1.send(queue, data);
                if(queue.equals(activeMqFactory1.getActiveMqProperties().getSendTopic())){
                    mainController.updateSendTopic1Num();
                }else if(queue.equals(activeMqFactory1.getActiveMqProperties().getSendCommandQueue())){
                    if(XmlConverter.isAck(data)){
                        return;
                    }
                    mainController.updateSendCommandQueue1Num();
                }else if(queue.equals(activeMqFactory1.getActiveMqProperties().getFplQueue())) {
                    mainController.updateSendFplQueue1Num();
                }
            }else if(source == 2){
                activeMqFactory2.send(queue, data);
                if(queue.equals(activeMqFactory2.getActiveMqProperties().getSendTopic())){
                    mainController.updateSendTopic2Num();
                }else if(queue.equals(activeMqFactory2.getActiveMqProperties().getSendCommandQueue())){
                    if(XmlConverter.isAck(data)){
                        return;
                    }
                    mainController.updateSendCommandQueue2Num();
                }else if(queue.equals(activeMqFactory2.getActiveMqProperties().getFplQueue())) {
                    mainController.updateSendFplQueue2Num();
                }
            }
           
            
        } catch (Exception e) {
            logger.error("sendMsg error {}", e.getMessage());
            throw new RuntimeException(e);
        }
    }
}
